#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>


#include "nrs1800_reg.h"
#include "nrs1800_config.h"

#define DEBUG       printf

/*
    RapidIO Capability Registers (CARs)
*/
#define DEVICE_ID_CAR_ADDR              (0x000000)
#define DEVICE_INFO_CAR_ADDR            (0x000004)
#define ASSEMBLEY_ID_CAR_ADDR           (0x000008)
#define ASSEMBLEY_INFO_CAR_ADDR         (0x00000C)

int nrs1800_reg_read(int fd, uint32_t reg, uint32_t *reg_data)
{
    int ret = 0;
    char buf[8] = {0};
    uint32_t reg_val = 0, reg_addr = 0;

    reg_addr = reg>>2;
    buf[0] = 0x80;
    buf[1] = (1<<6) | ((reg_addr&0xff0000)>>16);
    buf[2] = (reg_addr&0x00ff00)>>8;
    buf[3] = reg_addr&0xff;

    ret = read(fd, buf, 4);
    if( ret < 0 )
    {
        DEBUG("ERROR Writing\n");
        return -1;
    }

    reg_val = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
    *reg_data = reg_val;

    return 0;
}


// Opens the specified I2C device.  Returns a non-negative file descriptor
// on success, or -1 on failure.
int open_i2c_device(const char * device)
{
  int fd = open(device, O_RDWR);
  if (fd == -1)
  {
     perror(device);
     return -1;
  }
  return fd;
}
 

// Sets the target position, returning 0 on success and -1 on failure.
// @fd: The file descriptor
// @address: The target slave address
// @reg: The address of the read data
// @buffer: read data buffer
// @length: read data length
// @retval: 0 for success, -1 for failure.
int nrs1800_data_nwrite(int fd, uint16_t address, uint32_t reg, 
    uint8_t *buffer, uint32_t length)
{
    uint8_t command[3] = {};
    uint32_t reg_addr = 0;

    
    //DEBUG("%s line %d \n", __FUNCTION__, __LINE__);
    
    reg_addr = reg>>2;
    command[0] = (reg_addr&0xff0000)>>16;
    command[1] = (reg_addr&0x00ff00)>>8;
    command[2] = reg_addr&0xff;
    
    DEBUG("%s line %d \ndevice addr [%#x], reg addr [%#x] \n",\
            __FUNCTION__, __LINE__, address, reg);
    
    memcpy(command+3, buffer, length);
    
    struct i2c_msg message = { reg_addr, 0|I2C_M_TEN, length+3, command};
    struct i2c_rdwr_ioctl_data ioctl_data = { &message, 1 };
    /* 设置从机地址为10位 */
    ioctl(fd, I2C_TENBIT, 1);
    int result = ioctl(fd, I2C_RDWR, &ioctl_data);
    if (result != 1)
    {
        perror("failed to set target position");
        return -1;
    }

    return 0;
}
 
// Gets one or more variables from the eeprom
// @fd: The file descriptor
// @address: The target slave address
// @reg: The address of the read data
// @buffer: read data buffer, less 4byte
// @length: read data length, 4byte
// @retval: 0 for success, -1 for failure
int nrs1800_data_nread(int fd, uint16_t address, uint32_t reg,
    uint8_t *buffer, uint8_t length)
{
    uint8_t command[4] = {0};
    uint32_t reg_addr = 0;
    
    struct i2c_msg messages[] = {
        { address, 0|I2C_M_TEN, sizeof(command), command },
        { address, I2C_M_RD|I2C_M_TEN, length, buffer},
    };

    struct i2c_rdwr_ioctl_data ioctl_data = { messages, 2 };

    DEBUG("%s line %d \ndevice addr [%#x], reg addr [%#x] \n",\
            __FUNCTION__, __LINE__, address, reg);
    
    reg_addr = reg>>2;
    command[0] = 0x80;
    command[1] = (1<<6) | ((reg_addr&0xff0000)>>16);
    command[2] = (reg_addr&0x00ff00)>>8;
    command[3] = reg_addr&0xff;
    
    /* 设置从机地址为10位 */
    ioctl(fd, I2C_TENBIT, 1);
    int result = ioctl(fd, I2C_RDWR, &ioctl_data);
    if (result != 2)
    {
        perror("failed to get variables");
        return -1;
    }
    return 0;
}

/*
 *  格式：执行文件 设备节点 节点id
 * ./at24c02_test /dev/i2c-0 1
 * ./at24c02_test /dev/nrs1800_00 1
 */

int main(int argc, char **argv)
{
    int ret = 0;
    int fd, index, id;
    uint32_t reg_val;
    uint8_t read_buf[4] = {0};

    if (argc != 3)
    {
        printf("Usage: %s <dev>\n", argv[0]);
        return -1;
    }
    
    fd = open(argv[1], O_RDWR);
    if (fd < 0)
    {
        printf(" can not open %s\n", argv[1]);
        return -1;
    }

    id = atoi(argv[2]);
    
    while(1)
    {
        //ret = nrs1800_data_nread(fd, id, DEVICE_ID_CAR_ADDR, read_buf, 4);
        //DEBUG("get data [0x%02x%02x%02x%02x] of device id car registers\n", \
        //        read_buf[0], read_buf[1], read_buf[2], read_buf[3]);
        //memset(read_buf, 0, 4);
        
        ret = nrs1800_reg_read(fd, DEVICE_ID_CAR_ADDR, &reg_val);
        DEBUG("get data [%#x] of device id car registers\n", reg_val);
        sleep(1);
    }

    close(fd);
    return 0;
}


